package com.tegtech.core.handler;

import javax.validation.ValidationException;

import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.tegtech.common.domain.Result;
import com.tegtech.common.enums.HttpStatus;
import com.tegtech.common.exception.BaseException;
import com.tegtech.common.exception.BusinessException;

import lombok.extern.slf4j.Slf4j;

/**
 * 全局异常处理器
 * 
 * @author Jun
 */
@Slf4j
@Order(Integer.MAX_VALUE)
@RestControllerAdvice
public class GlobalExceptionHandler {

	/**
	 * 基础异常
	 */
	@ExceptionHandler(BaseException.class)
	public Result baseException(BaseException e) {
		return Result.err().msg(e.getMessage());
	}

	/**
	 * 业务异常
	 */
	@ExceptionHandler(BusinessException.class)
	public Result businessException(BusinessException e) {
		return Result.err(e);
	}

	/**
	 * NoHandler异常
	 */
	@ExceptionHandler(NoHandlerFoundException.class)
	public Result handlerNoFoundException(Exception e) {
		log.error(e.getMessage(), e);
		return Result.err(HttpStatus.NOT_FOUND);
	}

	@ExceptionHandler(AccessDeniedException.class)
	public Result handleAuthorizationException(AccessDeniedException e) {
		log.error(e.getMessage());
		return Result.err(HttpStatus.FORBIDDEN);
	}

	@ExceptionHandler(AccountExpiredException.class)
	public Result handleAccountExpiredException(AccountExpiredException e) {
		log.error(e.getMessage(), e);
		return Result.err().msg(e.getMessage());
	}

	@ExceptionHandler(UsernameNotFoundException.class)
	public Result handleUsernameNotFoundException(UsernameNotFoundException e) {
		log.error(e.getMessage(), e);
		return Result.err().msg(e.getMessage());
	}

	/**
	 * 参数校验异常
	 * @param e
	 * @return
	 */
	@ExceptionHandler(IllegalArgumentException.class)
	public Result illegalArgumentException(Exception e) {
		return Result.err().msg(e.getMessage());
	}
	
	/**
	 * 自定义验证异常
	 */
	@ExceptionHandler(BindException.class)
	public Result bindException(BindException e) {
		log.error(e.getMessage(), e);
		String message = e.getAllErrors().get(0).getDefaultMessage();
		return Result.err().msg(message);
	}

	/**
	 * 自定义验证异常
	 * @param e
	 * @return
	 */
	@ExceptionHandler(ValidationException.class)
    public Result validationException(ValidationException e) {
		String message = e.getMessage();
		int index = message.indexOf(":");
		if(index != -1) {
			message = message.substring(index + 2, message.length());
		}
		return Result.err().msg(message);
    }
	
	/**
	 * 自定义验证异常
	 */
	@ExceptionHandler(MethodArgumentNotValidException.class)
	public Object validExceptionHandler(MethodArgumentNotValidException e) {
		log.error(e.getMessage(), e);
		String message = e.getBindingResult().getFieldError().getDefaultMessage();
		return Result.err().msg(message);
	}

	/**
	 * 方法参数异常
	 * @param e
	 * @return
	 */
	@ExceptionHandler(MethodArgumentTypeMismatchException.class)
	public Result methodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e) {
		return Result.err(HttpStatus.PARAM_INVALID);
	}
	
	/**
	 * 通用异常处理
	 * @param e
	 * @return
	 */
	@ExceptionHandler(Exception.class)
	public Result commonException(Exception e) {
		log.error(e.getMessage(), e);
		return Result.err(HttpStatus.ERROR);
	}
	
}
